package com.huilian.iotbox.admin.wap.consumer;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.huilian.iotbox.admin.wap.config.DelayMQConfig;
import com.huilian.iotbox.admin.wap.service.*;
import com.huilian.iotbox.aliyun.service.PubService;
import com.huilian.iotbox.data.cmd.PositiveDataFrameCMD;
import com.huilian.iotbox.data.cmd.VendmachPositiveDataFrameCMD;
import com.huilian.iotbox.data.common.RedisKey;
import com.huilian.iotbox.data.dto.*;
import com.huilian.iotbox.data.enums.*;
import com.huilian.iotbox.data.po.*;
import com.huilian.iotbox.data.service.ErrorLogCommonService;
import com.huilian.iotbox.data.service.UploadService;
import com.huilian.iotbox.data.utils.CopyPropertiesUtils;
import com.huilian.iotbox.data.utils.MD5Util;
import com.huilian.iotbox.data.utils.SnowflakeIdWorker;
import com.huilian.iotbox.data.vo.*;
import com.huilian.tool.common.utils.HuiLianHttpUtil;
import com.rabbitmq.client.Channel;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.RandomStringUtils;
import org.springframework.amqp.rabbit.annotation.*;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.support.AmqpHeaders;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.messaging.handler.annotation.Headers;
import org.springframework.messaging.handler.annotation.Payload;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import java.io.IOException;
import java.io.Serializable;
import java.util.*;

@Component
@Slf4j
public class RabbitReceiver {

    @Value("${huilian.iot.productKey}")
    private String productKey;
    @Autowired
    private PubService pubService;
    @Autowired
    private DeviceService deviceService;
    @Autowired
    private UploadService uploadService;
    @Autowired
    private ErrorLogCommonService errorLogCommonService;
    @Autowired
    private RedisTemplate<String, Serializable> redisTemplate;
    @Autowired
    private ExternalDeviceParamValueService externalDeviceParamValueService;


    /**
     * 监听接收到延迟队列消息
     *
     * @param map
     * @param channel
     * @param headers
     * @throws IOException
     */
    @RabbitListener(queues = DelayMQConfig.IOT_BOX_WAP_LAZY_QUEUE)
    @RabbitHandler
    public void onReplayLazyQueue(@Payload Map<String, String> map, Channel channel, @Headers Map<String, Object> headers) throws IOException {
        try {
            log.info("监听接收到延迟队列消息-延迟发送消息");
            /**
             * 监听接收到延迟队列消息-延迟发送消息
             */
            String code = map.get("code");
            if (CompositeDelayQueueEnum.INITIATIVE_SEND_QUERY_BASE_PARAMS.getCode().equals(code)) {
                // 主动通过串口去查设备的参数
                Integer positionId = Integer.valueOf(map.get("positionId"));
                String tcp = PositiveDataFrameCMD.queryBaseParams();
                log.info("tcp:" + tcp);
                String penetrate;
                if (StringUtils.isEmpty(positionId)){
                    penetrate = PositiveDataFrameCMD.penetrate(tcp);
                } else {
                    penetrate = PositiveDataFrameCMD.penetrate32(positionId, tcp);
                }
                pubService.pub(penetrate, map.get("deviceNo"), productKey);
            } else if (CompositeDelayQueueEnum.BATCH_TRACK_TESTING.getCode().equals(code)) {
                // 主动通过串口去查设备的参数
                String deviceNo = map.get("deviceNo");
                String tcp = map.get("tcp");
                log.info("deviceNo:" + deviceNo);
                log.info("tcp:" + tcp);
                pubService.pub(tcp, deviceNo, productKey);
            } else if (CompositeDelayQueueEnum.NOTIFICATION_UPDATE.getCode().equals(code)) {
                // 主动通过串口去查设备的参数
                String deviceNo = map.get("deviceNo");
                String tcp = map.get("tcp");
                log.info("deviceNo:" + deviceNo);
                log.info("tcp:" + tcp);
                pubService.pub(tcp, deviceNo, productKey);
            } else if (CompositeDelayQueueEnum.SYNTHESIZE.getCode().equals(code)) {
                // 综合发送
                String deviceNo = map.get("deviceNo");
                String tcp = map.get("tcp");
                log.info("deviceNo:" + deviceNo);
                log.info("tcp:" + tcp);
                pubService.pub(tcp, deviceNo, productKey);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            Long deliveryTag = (Long) headers.get(AmqpHeaders.DELIVERY_TAG);
            //手工ACK
            channel.basicAck(deliveryTag, true);
        }
    }

    @RabbitListener(bindings = @QueueBinding(value = @Queue(value = "${spring.rabbitmq.listener.iotBoxRestockNotification" +
            ".queue.name}",
            durable = "${spring.rabbitmq.listener.iotBoxRestockNotification.queue.durable}"),
            exchange = @Exchange(value = "${spring.rabbitmq.listener.iotBoxRestockNotification.exchange.name}",
                    durable = "${spring.rabbitmq.listener.iotBoxRestockNotification.exchange.durable}",
                    type = "${spring.rabbitmq.listener.iotBoxRestockNotification.exchange.type}"),
            ignoreDeclarationExceptions = "${spring.rabbitmq.listener.iotBoxRestockNotification.exchange.ignoreDeclarationExceptions}",
            key = "${spring.rabbitmq.listener.iotBoxRestockNotification.key}"))
    @RabbitHandler
    public void iotBoxRestockNotification(@Payload JSONObject jsonObject, Channel channel, @Headers Map<String, Object> headers) throws IOException {
        try {
            log.info("从队列【{}】接收到消息:{}", "restockNotification", jsonObject);
            Map<String, String> requestParameters = new HashMap<>();
            String appKey = jsonObject.get("appKey").toString();
            String appSecret = jsonObject.get("appSecret").toString();
            String timestampD = String.valueOf(System.currentTimeMillis());
            String appKeyE = Base64.getEncoder().encodeToString(appKey.getBytes());
            String timestampE = Base64.getEncoder().encodeToString(timestampD.getBytes());
            String signatureE = MD5Util.md5Encrypt32Upper(String.format("%s%s%s", appKey, timestampD, appSecret));
            requestParameters.put("Authorization","Bearer-jetour");
            requestParameters.put("appKey",appKeyE);
            requestParameters.put("timestamp",timestampE);
            requestParameters.put("signature",signatureE);
            List<RestockNotificationVo> restockNotificationVoList =  JSONObject.parseArray(jsonObject.getString("restockNotificationList"),RestockNotificationVo.class);
            String results = HuiLianHttpUtil.httpPostJson(jsonObject.get("requestAddress").toString(), requestParameters,restockNotificationVoList);
            log.info("请求头:{}",requestParameters);
            log.info("{}设备补货通知请求参数:{}",jsonObject.get("deviceNo"),jsonObject.getString("restockNotificationList"));
            log.info("请求结果{}",results);
        } catch (Exception e) {
            e.printStackTrace();
            log.error("补货通知失败{}", e.toString());
            errorLogCommonService.writerInfoException("补货通知失败", jsonObject, e);
        } finally {
            Long deliveryTag = (Long) headers.get(AmqpHeaders.DELIVERY_TAG);
            //手工ACK
            channel.basicAck(deliveryTag, true);
        }
    }


    @RabbitListener(queues = DelayMQConfig.IOT_BOX_WAP_IMAGE_UPLOAD_DATE_PROCESSING_LAZY_QUEUE)
    @RabbitHandler
    public void onReplayImageUploadDateProcessingLazyQueue(@Payload String fileName, Channel channel, @Headers Map<String, Object> headers) throws IOException {
        try {
            log.info("进入图片上传过期处理");

            String key = String.format(RedisKey.FTP_IMAGE_DATE_PROCESSING, fileName);
            Serializable serializable = redisTemplate.opsForValue().get(key);
            if (StringUtils.isEmpty(serializable)) {
                uploadService.deleteByFileNameToFTP(fileName);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            Long deliveryTag = (Long) headers.get(AmqpHeaders.DELIVERY_TAG);
            //手工ACK
            channel.basicAck(deliveryTag, true);
        }
    }


    @RabbitListener(queues = DelayMQConfig.IOT_BOX_WAP_MERCHANT_SUBMIT_REMOVE_INFO_LAZY_QUEUE)
    @RabbitHandler
    public void onReplayMerchantSubmitRemoveInfoLazyQueue(@Payload String key, Channel channel, @Headers Map<String, Object> headers) throws IOException {
        try {
            log.info("进入商户提交进件，延迟删除缓存的信息，key：" + key);
            Boolean delete = redisTemplate.delete(key);
            log.info("进入商户提交进件，延迟删除缓存的信息：" + delete);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            Long deliveryTag = (Long) headers.get(AmqpHeaders.DELIVERY_TAG);
            //手工ACK
            channel.basicAck(deliveryTag, true);
        }
    }


    /**
     * @param map
     * @param channel
     * @param headers
     * @throws IOException
     */
    @RabbitListener(queues = DelayMQConfig.IOT_BOX_WAP_QUERY_EXTERNAL_DEVICE_PARAM_VALUE_LAZY_QUEUE)
    @RabbitHandler
    public void onReplayQueryExternalDeviceParamValueLazyQueue(@Payload Map<String, Object> map, Channel channel, @Headers Map<String, Object> headers) throws IOException {
        try {
            log.info("进入延迟查询外部设备基础参数的信息");
            ExternalDeviceParamValueDto externalDeviceParamValueDto = new ExternalDeviceParamValueDto();
            externalDeviceParamValueDto.setDeviceId((Integer) map.get("deviceId"));
            externalDeviceParamValueDto.setUserInfo((UserInfo) map.get("userInfo"));
            externalDeviceParamValueService.sendQueryExternalDeviceParamValue(externalDeviceParamValueDto);
            log.info("进入延迟查询外部设备基础参数的信息：" + externalDeviceParamValueDto.getDeviceId() + externalDeviceParamValueDto.getUserInfo());
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            Long deliveryTag = (Long) headers.get(AmqpHeaders.DELIVERY_TAG);
            //手工ACK
            channel.basicAck(deliveryTag, true);
        }
    }


    /**
     * @param map
     * @param channel
     * @param headers
     * @throws IOException
     */
    @RabbitListener(queues = DelayMQConfig.IOT_BOX_WAP_SEND_MOTOR_DETECTION_LAZY_QUEUE)
    @RabbitHandler
    public void onMotorDetectionEndLazyQueue(@Payload Map<String, String> map, Channel channel, @Headers Map<String, Object> headers) throws IOException {
        try {
            log.info("开始进去发送电机测试");
            String random = RandomStringUtils.random(6, true, true);
            if(!StringUtils.isEmpty(map.get("payNo"))) {
                random = map.get("payNo");
            }
            List<OrderItem> orderItemList = JSON.parseArray(map.get("orderItemList"), OrderItem.class);
            String command = null;
            if(map.get("deviceTypeId").equals(DeviceTypeEnum.OPEN_DOOR_VENDING_MACHINE.getCode().toString())){
                String cmd = "04";
                if(!StringUtils.isEmpty(map.get("cmd"))){
                     cmd = map.get("cmd");
                }
                command = PositiveDataFrameCMD.penetrate(VendmachPositiveDataFrameCMD.LatticeShipmentTestNew(map.get("deviceNo"),random, orderItemList,cmd));
            }else{
                command = PositiveDataFrameCMD.penetrate(VendmachPositiveDataFrameCMD.motorTesting(map.get("deviceNo"), random, orderItemList));
            }
            pubService.pub(command,map.get("deviceNo"), productKey);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            Long deliveryTag = (Long) headers.get(AmqpHeaders.DELIVERY_TAG);
            //手工ACK
            channel.basicAck(deliveryTag, true);
        }
    }
}
